#include <io.h>
#include <conio.h>
#include <stdio.h>

#include "sound.h"

Sound::Sound(): m_timer(0.0f) {}


/*******************************************************************
* Initializes DirectSound
*******************************************************************/
bool Sound::initDirectSound(HWND hwnd)
{
	HRESULT hr;

	hr = DirectSoundCreate8(NULL, &g_pDS, NULL);
	if FAILED (hr)
		return false;

	// Set DirectSound cooperative level 
    hr = g_pDS->SetCooperativeLevel(hwnd, DSSCL_PRIORITY);
	if FAILED (hr)
		return false;

	return true;
}

/*******************************************************************
* Releases the DirecSound device
*******************************************************************/
void Sound::shutdownDirectSound()
{
	if (g_pDS)
	{
		g_pDS->Release();
		g_pDS = NULL;
	}
}

/*******************************************************************
* Loads a wave file into a DirectSound Buffer
*******************************************************************/
LPDIRECTSOUNDBUFFER Sound::LoadWaveToSoundBuffer()
{
	LPDIRECTSOUNDBUFFER apDSBuffer = NULL;
	CWaveFile *wavFile;
	HRESULT hr;

	wavFile = new CWaveFile();
	wavFile->Open(/*(char*)*/m_sFilename/*.c_str()*/, NULL, WAVEFILE_READ);
	if (wavFile->GetSize() == 0)
	{
		//MessageBox(wndHandle, "invalid file", "ERROR", MB_OK);
		return false;
	}

	DSBUFFERDESC dsbd;
    ZeroMemory (&dsbd, sizeof(DSBUFFERDESC));
    dsbd.dwSize          = sizeof (DSBUFFERDESC);
    dsbd.dwFlags         = DSBCAPS_CTRLVOLUME | DSBCAPS_CTRLFREQUENCY | DSBCAPS_CTRLPAN; 
    dsbd.dwBufferBytes   = wavFile->GetSize();
    dsbd.guid3DAlgorithm = GUID_NULL;
	dsbd.lpwfxFormat     = wavFile->m_pwfx;

	hr = g_pDS->CreateSoundBuffer (&dsbd, &apDSBuffer, NULL);
	if FAILED (hr)
	{
		MessageBox (NULL, "unable to create sound buffer", "ERROR", MB_OK);
		return NULL;
	}

	VOID*   pDSLockedBuffer      = NULL; // Pointer to locked buffer memory
    DWORD   dwDSLockedBufferSize = 0;    // Size of the locked DirectSound buffer
    DWORD   dwWavDataRead        = 0;    // Amount of data read from the wav file 
	
	hr = apDSBuffer->Lock(0, wavFile->GetSize(), &pDSLockedBuffer, &dwDSLockedBufferSize, NULL, NULL, 0L);

	if FAILED (hr)
        return NULL;

    // Reset the wave file to the beginning 
    wavFile->ResetFile();

	// Read the wave file
    hr = wavFile->Read ((BYTE *) pDSLockedBuffer, dwDSLockedBufferSize, &dwWavDataRead);

	// Check to make sure that this was successful
	if FAILED (hr)
        return NULL;

	// Check to make sure the wav file is not empty
    if (dwWavDataRead == 0)
    {
        // Wav is blank, so just fill with silence
        FillMemory ((BYTE *) pDSLockedBuffer, 
                    dwDSLockedBufferSize, 
                    (BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0));
    }
    else if (dwWavDataRead < dwDSLockedBufferSize)
    {
	    // Don't repeat the wav file, just fill in silence 
        FillMemory ((BYTE*) pDSLockedBuffer + dwWavDataRead, 
                   dwDSLockedBufferSize - dwWavDataRead, 
                   (BYTE)(wavFile->m_pwfx->wBitsPerSample == 8 ? 128 : 0));
    }

    // Unlock the buffer, we don't need it anymore.
    apDSBuffer->Unlock (pDSLockedBuffer, dwDSLockedBufferSize, NULL, 0);

	// Clean up
	delete wavFile;

	m_pBuffer = apDSBuffer;

	m_pBuffer->GetFrequency(&m_dFreq);
	m_pBuffer->GetPan(&m_lPan);
	m_pBuffer->GetVolume(&m_lVol);

	/* How to Load a Wave File 
	Reference: http://www.cpp-home.com/tutorials/333_2.htm */
	
	FILE *file;
	
    char id[4]; 
    short formatTag, channels, blockAlign, bitsPerSample; // 16 bit values
    DWORD fileSize, formatLength, sampleRate, avgBytesSec; // 32 bit values
	
    file = fopen(m_sFilename,"rb");
    if (file)
    {
        fread(id, sizeof(char), 4, file); // Read in first four bytes

        if (strcmp(id, "RIFF") != 0)
		{ 
			// 'RIFF' 
            fread(&fileSize, sizeof(DWORD), 1, file); // Read in 32 bit size value
            fread(id, sizeof(char), 4, file);		// Read in 4 bytes string now
            if (strcmp(id, "WAVE") != 0)
            { 
				// Wave file 
                fread(id, sizeof(char), 4, file); // Read in 4 bytes "fmt ";
                fread(&formatLength, sizeof(DWORD),1,file);
                fread(&formatTag, sizeof(short), 1, file); 	

                fread(&channels, sizeof(short),1,file); // 1 mono, 2 stereo
                fread(&sampleRate, sizeof(DWORD), 1, file); // like 44100, 22050, etc...
                fread(&avgBytesSec, sizeof(DWORD), 1, file); // probably won't need this
                fread(&blockAlign, sizeof(short), 1, file); // probably won't need this
                fread(&bitsPerSample, sizeof(short), 1, file); // 8 bit or 16 bit file	
            } 
			else { printf("Error: RIFF file but not a wave file\n"); }
        } 
		else { printf("Error: not a RIFF file\n"); }
    }
	m_fDur = ((float)fileSize/(float)avgBytesSec);

	return apDSBuffer;
}

void Sound::playSound() { m_pBuffer->Play(0, 0, 0); }

void Sound::playSoundLoop() { m_pBuffer->Play(0, 0, DSBPLAY_LOOPING); }

void Sound::stopSound() { m_pBuffer->Stop(); }

void Sound::Update(float elapsedTime) { m_timer += elapsedTime; }

void Sound::setHWND(HWND a_hwnd) { m_hwnd = a_hwnd; }

void Sound::setFilename(char *a_sFilename) { m_sFilename = a_sFilename; }

void Sound::setBuffer(LPDIRECTSOUNDBUFFER a_pBuffer) { m_pBuffer = a_pBuffer; }

void Sound::setVol(long a_lVol)
{
	m_lVol = a_lVol;
	m_pBuffer->SetVolume(m_lVol);
}
void Sound::setPan(long a_lPan)
{
	m_lPan = a_lPan;
	m_pBuffer->SetPan(m_lPan);
}

void Sound::setFreq(DWORD a_dFreq, float a_fFreqDivisor)
{
	m_dFreq = (DWORD)(a_dFreq/(float)a_fFreqDivisor);
	m_pBuffer->SetFrequency(m_dFreq);
}
